import ctypes
import logging
import platform
import sys
import time

import numpy as np

from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtGui import QIcon
from PyQt5.QtNetwork import QLocalSocket, QLocalServer
from PyQt5.QtWidgets import QMainWindow, QStatusBar

import errorhandle
from configs.strings import combox, translate
from configs.udpconfig import UDPConfigDialog
from connexions.udpcollectorthread import UDPServer
from tools import tools
from tools.parser import parse_parameters
from tools.tools import basic_log_config, load_yaml, save_data
from tools.workthread import WorkThread
from wavegraph import WaveGraph


class MainFrame(QMainWindow):
    def __init__(self):
        super(MainFrame, self).__init__()
        basic_log_config()
        self.configs = load_yaml()
        self.lang = combox[self.configs["APP"]["LANGUAGE"]]
        self.init_args()
        self.init_ui()
        self.init_central_panel()
        self.init_widget_status()
        self.connect_slots()

    def init_ui(self):
        """
        Initialize the UI
        :return:
        """
        sys = platform.system()
        if sys == "Windows":
            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
                self.configs["APP"]["APP_NAME"])
        self.mainLayout = QtWidgets.QGridLayout()
        self.mainLayout.setObjectName("mainLayout")
        self.setGeometry(QtCore.QRect(0, 0, 1200, 900))
        self.mainWidget = QtWidgets.QWidget()
        self.mainWidget.setLayout(self.mainLayout)
        self.setWindowTitle(self.configs["APP"]["APP_NAME"].replace('_', ' '))
        self.setWindowIcon(QIcon(self.configs["APP"]["ICON"]))
        # self.directory = appconfig.DEFAULT_SAVE_PATH

        self.menubar = self.menuBar()
        self.menuFile = self.menuBar().addMenu(translate['FILE'][self.lang])
        self.actionSaveData = QtWidgets.QAction(translate['SAVE_DATA'][self.lang])
        self.menuFile.addAction(self.actionSaveData)
        self.menubar.addAction(self.menuFile.menuAction())

        self.menuConfiguration = self.menubar.addMenu(translate['CONFIG'][self.lang])
        self.actionUDPConfig = QtWidgets.QAction(translate['UDP_CONFIG'][self.lang])
        self.menuConfiguration.addAction(self.actionUDPConfig)
        self.menubar.addAction(self.menuConfiguration.menuAction())

        self.menuFunction = self.menuBar().addMenu(translate['FUNCTION'][self.lang])
        self.actionShowAll = QtWidgets.QAction(translate['SHOW_ALL'][self.lang])
        # self.actionReStartUDP = QtWidgets.QAction(translate['RESTART_UDP'][self.lang])
        self.menuFunction.addAction(self.actionShowAll)
        # self.menuFunction.addAction(self.actionReStartUDP)
        self.menubar.addAction(self.menuFunction.menuAction())

        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)

        # TOOLBAR
        self.toolbarLayout = QtWidgets.QHBoxLayout()
        configGroupBox = QtWidgets.QGroupBox("")
        configGroupBox.setLayout(self.toolbarLayout)

        self.startButton = QtWidgets.QToolButton()
        self.startButton.setText(translate["START"][self.lang])
        self.startButton.setObjectName("startButton")
        self.startButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
        self.startButton.setIcon(QtGui.QIcon(self.configs['APP']['START_COL_ICON']))
        self.startButton.setIconSize(QtCore.QSize(50, 50))

        self.resetButton = QtWidgets.QToolButton()
        self.resetButton.setText(translate["RESET"][self.lang])
        self.resetButton.setObjectName("resetButton")
        self.resetButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
        self.resetButton.setIcon(QtGui.QIcon(self.configs['APP']['RESET_COL_ICON']))
        self.resetButton.setIconSize(QtCore.QSize(50, 50))

        self.stopButton = QtWidgets.QToolButton()
        self.stopButton.setText(translate['STOP'][self.lang])
        self.stopButton.setObjectName("stopButton")
        self.stopButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
        self.stopButton.setIcon(QtGui.QIcon(self.configs['APP']['STOP_COL_ICON']))
        self.stopButton.setIconSize(QtCore.QSize(50, 50))

        self.settingButton = QtWidgets.QToolButton()
        self.settingButton.setText(translate['SET_PARAM'][self.lang])
        self.settingButton.setObjectName("settingButton")
        self.settingButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
        self.settingButton.setIcon(QtGui.QIcon(self.configs['APP']['RESET_COL_ICON']))
        self.settingButton.setIconSize(QtCore.QSize(50, 50))

        # DEVICE CONFIG TO SEND
        self.configLayout = QtWidgets.QGridLayout()
        initF = eval(self.configs['DEVICE_CONFIG']['INIT_FREQ']) / 1e6
        endF = eval(self.configs['DEVICE_CONFIG']['END_FREQ']) / 1e6
        self.initFreqLabel = QtWidgets.QLabel(translate['INI_FREQ'][self.lang])
        self.initFreqLabel.setAlignment(QtCore.Qt.AlignRight)
        self.initFreqEdit = QtWidgets.QLineEdit(str(initF))
        self.initFreqEdit.setAlignment(QtCore.Qt.AlignLeft)

        self.endFreqLabel = QtWidgets.QLabel(translate['END_FREQ'][self.lang])
        self.endFreqLabel.setAlignment(QtCore.Qt.AlignRight)
        self.endFreqEdit = QtWidgets.QLineEdit(str(endF))
        self.endFreqEdit.setAlignment(QtCore.Qt.AlignLeft)

        self.filterPipeLabel = QtWidgets.QLabel(translate['FILTER_PIPE'][self.lang])
        self.filterPipeLabel.setAlignment(QtCore.Qt.AlignRight)
        tempFilterList = combox['FILTER_PIPE']
        tempFilter = str(self.configs['DEVICE_CONFIG']['FILTER_PIPE'])
        if tempFilter in tempFilterList:
            target = tempFilterList.index(tempFilter)
            if target != 0:
                tempFilterList[0], tempFilterList[target] = tempFilter, tempFilterList[0]
        self.filterPipeCombo = QtWidgets.QComboBox()
        self.filterPipeCombo.addItems(tempFilterList)

        self.impulseTimerLabel = QtWidgets.QLabel(translate['IMPULSE_TIMER'][self.lang])
        self.impulseTimerLabel.setAlignment(QtCore.Qt.AlignRight)
        self.impulseTimerEdit = QtWidgets.QLineEdit(str(self.configs['DEVICE_CONFIG']['IMPULSE_TIMER']))
        self.impulseTimerEdit.setAlignment(QtCore.Qt.AlignLeft)

        freqPts = int(eval(self.configs['DEVICE_CONFIG']['FREQ_PTS']) / 1e6)
        self.freqPtsLabel = QtWidgets.QLabel(translate['FREQ_PTS'][self.lang])
        self.freqPtsLabel.setAlignment(QtCore.Qt.AlignRight)
        self.freqPtsEdit = QtWidgets.QLineEdit(str(freqPts))
        self.freqPtsEdit.setAlignment(QtCore.Qt.AlignLeft)

        self.freqDiffLabel = QtWidgets.QLabel(translate['FREQ_DIFF'][self.lang])
        self.freqDiffLabel.setAlignment(QtCore.Qt.AlignRight)
        self.freqDiffEdit = QtWidgets.QLineEdit(str(self.configs['DEVICE_CONFIG']['FREQ_DIFF']))
        self.freqDiffEdit.setAlignment(QtCore.Qt.AlignLeft)

        self.singleFreqTimerLabel = QtWidgets.QLabel(translate['SINGLE_FREQ_TIMER'][self.lang])
        self.singleFreqTimerLabel.setAlignment(QtCore.Qt.AlignRight)
        self.singleFreqTimerEdit = QtWidgets.QLineEdit(str(self.configs['DEVICE_CONFIG']['SINGLE_FREQ_TIMER']))
        self.singleFreqTimerEdit.setAlignment(QtCore.Qt.AlignLeft)

        self.singleFreqIntervalLabel = QtWidgets.QLabel(translate['SINGLE_FREQ_INTERVAL'][self.lang])
        self.singleFreqIntervalLabel.setAlignment(QtCore.Qt.AlignRight)
        self.singleFreqIntervalEdit = QtWidgets.QLineEdit(str(self.configs['DEVICE_CONFIG']['SINGLE_FREQ_INTERVAL']))
        self.singleFreqIntervalEdit.setAlignment(QtCore.Qt.AlignLeft)

        self.configLayout.addWidget(self.initFreqLabel, 0, 0, 1, 1)
        self.configLayout.addWidget(self.initFreqEdit, 0, 1, 1, 2)
        self.configLayout.addWidget(self.endFreqLabel, 0, 3, 1, 1)
        self.configLayout.addWidget(self.endFreqEdit, 0, 4, 1, 2)
        self.configLayout.addWidget(self.filterPipeLabel, 0, 6, 1, 1)
        self.configLayout.addWidget(self.filterPipeCombo, 0, 7, 1, 2)
        self.configLayout.addWidget(self.impulseTimerLabel, 0, 9, 1, 1)
        self.configLayout.addWidget(self.impulseTimerEdit, 0, 10, 1, 2)

        self.configLayout.addWidget(self.freqPtsLabel, 1, 0, 1, 1)
        self.configLayout.addWidget(self.freqPtsEdit, 1, 1, 1, 2)
        self.configLayout.addWidget(self.freqDiffLabel, 1, 3, 1, 1)
        self.configLayout.addWidget(self.freqDiffEdit, 1, 4, 1, 2)
        self.configLayout.addWidget(self.singleFreqTimerLabel, 1, 6, 1, 1)
        self.configLayout.addWidget(self.singleFreqTimerEdit, 1, 7, 1, 2)
        self.configLayout.addWidget(self.singleFreqIntervalLabel, 1, 9, 1, 1)
        self.configLayout.addWidget(self.singleFreqIntervalEdit, 1, 10, 1, 2)

        self.toolbarLayout.addWidget(self.startButton)
        self.toolbarLayout.addWidget(self.resetButton)
        self.toolbarLayout.addWidget(self.stopButton)
        self.toolbarLayout.addWidget(self.settingButton)
        self.toolbarLayout.addLayout(self.configLayout)
        self.mainLayout.addWidget(configGroupBox, 0, 0, 2, 1)

        self.infoLayout = QtWidgets.QFormLayout()
        self.infoLayout.setAlignment(QtCore.Qt.AlignRight)
        self.countLabel = QtWidgets.QLabel(translate['COUNTER'][self.lang] + ': ')
        self.countStr = QtWidgets.QLabel('0')
        self.countStr.setAlignment(QtCore.Qt.AlignLeft)
        self.infoLayout.addRow(self.countLabel, self.countStr)

        self.mainLayout.addLayout(self.infoLayout, 2, 0, 1, 1)

    def init_central_panel(self):
        # Wave graph
        self.centralLayout = QtWidgets.QGridLayout()
        self.waveGraphA = WaveGraph(self.configs['APP']['UPDATE_NUM'])
        self.centralLayout.addWidget(self.waveGraphA, 0, 0, 1, 1)

        self.waveGraphB = WaveGraph(self.configs['APP']['UPDATE_NUM'])
        self.centralLayout.addWidget(self.waveGraphB, 1, 0, 1, 1)

        self.mainLayout.addLayout(self.centralLayout, 3, 0, 10, 1)
        self.setCentralWidget(self.mainWidget)

    def connect_slots(self):
        self.actionUDPConfig.triggered.connect(self.udp_server_config)
        self.actionSaveData.triggered.connect(self.save_curr_data_action)
        self.actionShowAll.triggered.connect(self.draw_all_pts_action)
        # self.actionReStartUDP.triggered.connect(self.restart_udp_action)

        self.startButton.clicked.connect(self.start_collection_action)
        self.resetButton.clicked.connect(self.reset_device_action)
        self.stopButton.clicked.connect(self.stop_collection_action)
        self.settingButton.clicked.connect(self.setting_device_action)

        self.collector = UDPServer(self.configs['UDP_CLIENT'])
        self.collector.trigger.connect(self.handle_uwb_data_action)
        self.collector.triggerInfo.connect(self.handle_uwb_info_action)
        self.collector.triggerExcept.connect(self.handle_udp_exception_action)
        if self.collector.connect_server() == 0:
            self.collector.isRunning = True
            self.collector.start()
            self.uwbInfoCount = 0
            self.collectorInfoTimer = QtCore.QTimer(self)
            self.collectorInfoTimer.timeout.connect(self.init_info_uwb_action)
            self.collectorInfoTimer.start(1000)
            self.counterTimer = QtCore.QTimer(self)
            self.counterTimer.timeout.connect(self.counter_uwb_action)
            self.counterTimer.start(1)

        self.waveAThread = WorkThread(freq=self.configs['APP']['DRAW_WAVE_FREQ'])
        self.waveAThread.signal_updateUI.connect(self.draw_pics_action)

    def init_args(self):
        self.count = 0
        self.drawCount = 0
        self.uwbData = []
        self.uwbInfo = []
        self.currUwbData = []
        self.isCollecting = False
        self.isRecvInfo = False

    def init_widget_status(self):
        self.stopButton.setEnabled(False)
        self.startButton.setEnabled(False)
        self.resetButton.setEnabled(False)
        self.initFreqEdit.setEnabled(False)
        self.endFreqEdit.setEnabled(False)
        self.freqDiffEdit.setEnabled(False)
        self.freqPtsEdit.setEnabled(False)
        self.impulseTimerEdit.setEnabled(False)
        self.singleFreqIntervalEdit.setEnabled(False)
        self.singleFreqTimerEdit.setEnabled(False)
        self.filterPipeCombo.setEnabled(False)

    def init_info_uwb_action(self):
        """
        QTimer初始化设备计时器的槽函数
        在开始采集前需要不停发初始化命令到设备，以便获得MAC和IP地址，获得后停止发送Init命令
        :return:
        """
        if not self.isRecvInfo:
            cmdRes = self.collector.execute_cmd(cmd='init')
            if cmdRes == 0:
                pass
            else:
                self.collector.stop()
                self.collectorInfoTimer.stop()
                logging.error("Unable to send init cmd to uwb...")
                tools.show_dialog(self, 'Unable to send 28 00 01 00 01 to device..Error Code: ' + str(cmdRes),
                                  tools.ERROR)
        # if self.uwbInfoCount > 16:
        #     tools.show_dialog(self, 'Can not connect to device..', tools.ERROR)
        #     self.collector.stop()
        #     self.collectorInfoTimer.stop()
        else:
            self.collectorInfoTimer.stop()
        self.uwbInfoCount += 1

    def handle_uwb_info_action(self, info):
        """
        获取设备MAC/IP槽函数, 现设到设备并初始化控件状态
        :param info: 解析后的MAC/IP以及raw data
        :return:
        """
        logging.info("Rec info from uwb.." + str(info))
        self.isRecvInfo = True
        self.uwbInfo = info
        self.startButton.setEnabled(True)
        self.resetButton.setEnabled(False)
        self.stopButton.setEnabled(False)
        self.settingButton.setEnabled(True)
        self.initFreqEdit.setEnabled(True)
        self.endFreqEdit.setEnabled(True)
        self.freqDiffEdit.setEnabled(True)
        self.freqPtsEdit.setEnabled(True)
        self.impulseTimerEdit.setEnabled(True)
        self.singleFreqIntervalEdit.setEnabled(True)
        self.singleFreqTimerEdit.setEnabled(True)
        self.filterPipeCombo.setEnabled(True)
        self.statusBar.showMessage('Connect to Device successfully! IP: ' + self.uwbInfo[-1] + ', MAC: ' + self.uwbInfo[-2], 0)

    def counter_uwb_action(self):
        if self.isCollecting:
            if self.count % self.configs['APP']['SENT_CONTINUE_INTERVAL'] == 0:
                if self.convert_send_param() != 0:
                    logging.info("Re-send parameters failed...")
                    self.stop_collection_action()
                    return

    def handle_uwb_data_action(self, data):
        """
        获取设备数据的槽函数， 根据接收到的数据图像化到界面
        :param data: 解析后的数据
        :return:
        """
        if self.isCollecting:
            # if self.count % self.configs['APP']['SENT_CONTINUE_INTERVAL'] == 0:
            #     if self.convert_send_param() != 0:
            #         logging.info("Re-send parameters failed...")
            #         self.stop_collection_action()
            #         return
            self.uwbData.extend(data)
            if len(self.uwbData) > self.configs['APP']['UPDATE_NUM']:
                self.currUwbData = np.array(self.uwbData[-self.configs['APP']['UPDATE_NUM']:], dtype=float).T
            else:
                self.currUwbData = np.array(self.uwbData, dtype=float).T
            # Normalization data
            for i in range(0, self.currUwbData.shape[0]):
                self.currUwbData[i] = tools.normalization(self.currUwbData[i])
            self.count += 1
            self.countStr.setText(str(self.count))

    def handle_udp_exception_action(self, errCode):
        """
        负责处理接收数据信息等时候出现的异常
        :param errCode:
        :return:
        """
        if errCode == errorhandle.START_SERVER_EXCEPTION:
            self.collectorInfoTimer.stop()
            tools.show_dialog(self, 'Connect to device failed..', tools.ERROR)
        else:
            self.collectorInfoTimer.stop()
            logging.error("Exception occur at udp server : " + str(errCode))
            # tools.show_dialog(self, 'Something is wrong.. Error Code: ' + str(errCode), tools.ERROR)

    def draw_pics_action(self):
        if self.isCollecting and self.count > 0:
            if self.currUwbData.shape[0] == 4:
                self.waveGraphA.handle_data(self.currUwbData[0], self.currUwbData[2])
                self.waveGraphB.handle_data(self.currUwbData[1], self.currUwbData[3])
                # self.waveGraphC.handle_data(self.currUwbData[2])
                # self.waveGraphD.handle_data(self.currUwbData[3])

    def draw_all_pts_action(self):
        if self.isCollecting:
            tools.show_dialog(self, 'App is in collecting mode...Please stop it firstly', tools.ERROR)
            return
        else:
            if len(self.uwbData) > 0:
                transUwbData = np.array(self.uwbData).T
                self.waveGraphA.handle_data(tools.normalization(transUwbData[0]), tools.normalization(transUwbData[2]))
                self.waveGraphB.handle_data(tools.normalization(transUwbData[1]), tools.normalization(transUwbData[3]))
                # self.waveGraphC.handle_data(tools.normalization(transUwbData[2]))
                # self.waveGraphD.handle_data(tools.normalization(transUwbData[3]))
            else:
                tools.show_dialog(self, 'No data to show you silly!', tools.ERROR)

    # def restart_udp_action(self):
    #     logging.info("Restart ")
    #     self.collector.stop()
    #     self.collector.disconnect()
    #     if self.collector.connect_server() == 0:
    #         self.collector.isRunning = True
    #         self.collector.start()
    #         self.collectorInfoTimer.start(1000)

    def start_collection_action(self):
        logging.info("Start collections...")
        if self.check_config_action() == 0:
            pass
        else:
            return
        if self.convert_send_param() == 0:
            self.count = 0
            self.currUwbData = []
            self.uwbData = []
            self.waveGraphA.init_args()
            self.waveGraphB.init_args()
            self.isCollecting = True
            self.collector.isRunning = True

            self.startButton.setEnabled(False)
            self.stopButton.setEnabled(True)
            self.resetButton.setEnabled(True)
            self.settingButton.setEnabled(False)
            self.initFreqEdit.setEnabled(False)
            self.endFreqEdit.setEnabled(False)
            self.freqDiffEdit.setEnabled(False)
            self.freqPtsEdit.setEnabled(False)
            self.impulseTimerEdit.setEnabled(False)
            self.singleFreqIntervalEdit.setEnabled(False)
            self.singleFreqTimerEdit.setEnabled(False)
            self.filterPipeCombo.setEnabled(False)
            self.waveAThread.start()

    def setting_device_action(self):
        logging.info("Setting action is invoked...")
        if self.check_config_action() == 0:
            pass
        else:
            return
        if self.convert_send_param(isReset=True) != 0:
            tools.show_dialog(self, 'Send Setting CMD failed...', tools.ERROR)

    def reset_device_action(self):
        logging.info("Reset action is invoked...")
        if self.check_config_action() == 0:
            pass
        else:
            return
        if self.convert_send_param(isReset=True) != 0:
            tools.show_dialog(self, 'Send Reset CMD failed...', tools.ERROR)
            time.sleep(0.5)
            if self.convert_send_param(isReset=False) != 0:
                tools.show_dialog(self, 'Send Reset CMD failed...', tools.ERROR)
        # else:
        #     time.sleep(0.5)
        #     if self.convert_send_param(isReset=True) != 0:
        #         tools.show_dialog(self, 'Send Reset CMD failed...', tools.ERROR)

    def convert_send_param(self, isReset=False):
        logging.info("Build parameters to send to device..isReset=" + str(isReset))
        bParam = parse_parameters(self.configs['DEVICE_CONFIG'], self.uwbInfo[0], isReset)
        logging.info("Param is built: length/data " + str(len(bParam)) + '/' + bParam.hex())
        if len(bParam) != 49:
            tools.show_dialog(self, 'Parse parameter exception..', tools.ERROR)
            self.handle_udp_exception_action(errorhandle.PARSE_INSTRUCT_EXCEPTION)
            return errorhandle.PARSE_INSTRUCT_EXCEPTION
        return self.collector.execute_cmd(cmd='start', para=bParam)

    def check_config_action(self):
        logging.info("Check configuration which will be sent to device...")
        try:
            initFreq = float(self.initFreqEdit.text())
            endFreq = float(self.endFreqEdit.text())
            if initFreq > endFreq or (initFreq > 600 or initFreq < 0) or (endFreq > 6e3 or endFreq < 0):
                tools.show_dialog(self, 'init freq/end freq setting error, please check it!', tools.ERROR)
                return

            freqPts = int(self.freqPtsEdit.text())
            if freqPts > 1000 or freqPts < 2:
                tools.show_dialog(self, 'freq points setting error, please check it!', tools.ERROR)
                return

            pulseTimer = int(self.impulseTimerEdit.text())
            if pulseTimer < 0 or pulseTimer > 1e6:
                tools.show_dialog(self, 'pulse time setting error, please check it!', tools.ERROR)
                return

            freqDiff = int(self.freqDiffEdit.text())
            if freqDiff < 0 or freqDiff > 6e9:
                tools.show_dialog(self, 'freq difference setting error, please check it!', tools.ERROR)
                return

            singleFreqTimer = int(self.singleFreqTimerEdit.text())
            if singleFreqTimer < self.configs['DEVICE_CONFIG']['SINGLE_FREQ_TIMER_MIN'] or singleFreqTimer > 1e6:
                tools.show_dialog(self, 'single freq setting error, please check it!', tools.ERROR)
                return
            singleFreqTimer = int((singleFreqTimer -
                                   self.configs['DEVICE_CONFIG']['SINGLE_FREQ_TIMER_MIN']) /
                                  self.configs['DEVICE_CONFIG']['SINGLE_FREQ_FACTOR'])

            singleFreqInterval = float(self.singleFreqIntervalEdit.text())
            if singleFreqInterval < self.configs['DEVICE_CONFIG']['SINGLE_FREQ_INTERVAL_MIN'] or \
                    singleFreqInterval > 1e6:
                tools.show_dialog(self, 'single freq interval setting error, please check it!', tools.ERROR)
                return
            singleFreqInterval = int((singleFreqInterval - self.configs['DEVICE_CONFIG']['SINGLE_FREQ_INTERVAL_MIN'])
                                     / self.configs['DEVICE_CONFIG']['SINGLE_FREQ_FACTOR'])

            self.configs['DEVICE_CONFIG']['INIT_FREQ'] = int(initFreq * 1e6)
            self.configs['DEVICE_CONFIG']['END_FREQ'] = int(endFreq * 1e6)
            self.configs['DEVICE_CONFIG']['FREQ_PTS'] = int(freqPts)
            self.configs['DEVICE_CONFIG']['FREQ_DIFF'] = freqDiff
            self.configs['DEVICE_CONFIG']['SINGLE_FREQ_TIMER'] = singleFreqTimer
            self.configs['DEVICE_CONFIG']['IMPULSE_TIMER'] = pulseTimer
            self.configs['DEVICE_CONFIG']['SINGLE_FREQ_INTERVAL'] = singleFreqInterval
            self.configs['DEVICE_CONFIG']['FILTER_PIPE'] = self.filterPipeCombo.currentIndex()
            logging.info("Update configurations: " + str(self.configs['DEVICE_CONFIG']))
            return 0
        except:
            tools.show_dialog(self, 'Parameter setting is incorrect, please check it!', tools.ERROR)
            return

    def stop_collection_action(self):
        logging.info("Stop collections...")
        self.isCollecting = False
        # self.collector.stop()
        # self.waveAThread.stop()
        self.startButton.setEnabled(True)
        self.resetButton.setEnabled(False)
        self.stopButton.setEnabled(False)
        self.settingButton.setEnabled(True)
        self.initFreqEdit.setEnabled(True)
        self.endFreqEdit.setEnabled(True)
        self.freqDiffEdit.setEnabled(True)
        self.freqPtsEdit.setEnabled(True)
        self.impulseTimerEdit.setEnabled(True)
        self.singleFreqIntervalEdit.setEnabled(True)
        self.singleFreqTimerEdit.setEnabled(True)
        self.filterPipeCombo.setEnabled(True)
        self.statusBar.showMessage(
            'Connect to Device successfully! IP: ' + self.uwbInfo[-1] + ', MAC: ' + self.uwbInfo[-2], 0)

    def udp_server_config(self):
        logging.info("Configuration UDP Client dialog is invoked...")
        v = UDPConfigDialog(self.configs["UDP_CLIENT"], self.lang)
        if v.exec_():
            res = v.get_data()
            if res:
                self.configs["UDP_CLIENT"] = res
                # if type(self.collector) == SerialDataThread:
                #     self.collector.reload_configuration(self.configs["SERIAL"])
                logging.info("Update UDP Client config to: " + str(self.configs["UDP_CLIENT"]))
            else:
                logging.info("UDP Client configs has no change.")

    def save_curr_data_action(self):
        logging.info('Save data action is invoked...File type: ' + self.configs['APP']['SAVE_TYPE'])
        if len(self.uwbData) > 0:
            res = save_data(self.uwbData, instType='uwb', filetype=self.configs['APP']['SAVE_TYPE'])
            if res == errorhandle.SAVE_DAVE_ERROR:
                tools.show_dialog(self, 'Save file exception, error code:' + str(res), tools.ERROR)
                return
            else:
                self.collector.save_rawdata()
                tools.show_dialog(self, 'Save file done, find it at ./data', tools.INFO)
            logging.info('Save uwb file done at: ' + str(res))

        else:
            tools.show_dialog(self, 'Current rebar data or radar data is empty!', tools.WARNING)

    def closeEvent(self, a0: QtGui.QCloseEvent):
        """
        The action should be done before close the program.
        """
        if self.isCollecting:
            self.stop_collection_action()
        if self.collector:
            self.collector.stop()
            self.collector.execute_cmd('stop')
            self.collector.disconnect()


if __name__ == '__main__':
    basic_log_config()
    app = QtWidgets.QApplication(sys.argv)
    app_name = load_yaml(tools.CONFIG_FILE)["APP"]["APP_NAME"].replace('_', ' ')
    try:
        socket = QLocalSocket()
        socket.connectToServer(app_name)
        if socket.waitForConnected(500):
            tools.message_box("错误", "该程序正在运行中！")
            app.quit()
        else:
            local_server = QLocalServer()
            local_server.listen(app_name)
            main_window = MainFrame()
            main_window.show()
            sys.exit(app.exec_())
    except Exception as e:
        import traceback

        traceback.print_exc()
        tools.message_box("错误", "启动失败： " + str(e))
